package net.esj.basic.dao.jdbc.jpa;

import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

import javax.persistence.Table;
import javax.persistence.Transient;

import org.springframework.core.annotation.AnnotationUtils;
/**
 * 体现表结构和实体类之间映射关系的类。
 */
public class TableBeanMapping{
	private String tableName;
	private Class entityType;
	private Column[] columns;
	private PropertyDescriptor[] propertyDescriptors;
	private Column[] pkColumns;
	private PropertyDescriptor[] pkPropertyDescriptors;
	public int getIndexOfColName(String colName){
		int i = 0;
		for (Column col : columns) {
			if(colName.equalsIgnoreCase(col.getColumnName()))return i;
			i++;
		}
		return -1;
	}
	public String getColumnName(String proName) {
		int i = 0;
		for (PropertyDescriptor pd : pkPropertyDescriptors) {
			if(pd.getName().equalsIgnoreCase(proName))return columns[i].getColumnName();
			i++;
		}
		return null;
	}

	public Column[] getColumns() {
		return columns;
	}


	public String getTableName() {
		return tableName;
	}
	/**
	 * 分析实体类。
	 * 从该实体类的annotation配置中获取相关信息，然后存储在一个TableBeanMapping对象里。
	 * 
	 * @param entityType
	 * @return
	 */
	public static TableBeanMapping parseEntityType(Class entityType){
		TableBeanMapping mapping = new TableBeanMapping();
		Annotation[] classAnnotations = entityType.getAnnotations();
		String tableName = null;
		for (Annotation annotation : classAnnotations) {
			if(annotation instanceof Table){
				Table table = (Table)annotation;
				tableName = table.name();
			}
		}
		if(tableName == null)tableName = entityType.getSimpleName();
		mapping.setTableName(tableName);
		mapping.setEntityType(entityType);
		//开始处理字段名。
		BeanInfo beanInfo = null;
        try {
			beanInfo = Introspector.getBeanInfo(entityType);
		} catch (IntrospectionException e) {
			throw new RuntimeException(e.getMessage(),e);
		}
		//遍历所有的属性，将含Transient的跳过，其他的加入pds里。
    	PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
    	List<PropertyDescriptor> pds = new ArrayList();
    	List<PropertyDescriptor> pkPds = new ArrayList();
    	List<Column> cols = new ArrayList();
    	List<Column> pkColumns = new ArrayList();
    	for (int i = 0; i < propertyDescriptors.length; i++) {
    		//拼装一个propertyMapping。
    		PropertyDescriptor pd = propertyDescriptors[i];
    		String pdName = pd.getName();
    		if("class".equals(pdName))continue;
    		Method m = pd.getReadMethod();
    		//如果是Transient那么就跳过去了。
    		Transient tran = AnnotationUtils.getAnnotation(m, Transient.class);
    		if(tran != null)continue;
    		pds.add(pd);
    		
    		Column col = new Column();
    		cols.add(col);
    		Annotation[] annotations = AnnotationUtils.getAnnotations(m);
    		String colName = null;
    		if(annotations == null || annotations.length == 0){
    			colName = pdName;
    		}else{
    			//现在只写了获取字段名的代码。
    			for (int j = 0; j < annotations.length; j++) {
    				Annotation annotation = annotations[j];
    				if(annotation instanceof javax.persistence.Column){
    					String annotationColName = ((javax.persistence.Column)annotation).name();
    					if(annotationColName != null && !"".equals(annotationColName))
    						colName = annotationColName;
    				}else if(annotation instanceof javax.persistence.Id){
    					pkColumns.add(col);
    					pkPds.add(pd);
    				}
    			}
    		}
    		if(colName == null)colName = pdName;
    		col.setColumnName(colName);
		}
    	//转化为数组。
    	PropertyDescriptor[] pdArr = new PropertyDescriptor[pds.size()];
    	Column[] colsArr = new Column[pds.size()];
    	pds.toArray(pdArr);
    	cols.toArray(colsArr);
    	mapping.setPropertyDescriptors(pdArr);
    	mapping.setColumns(colsArr);
    	
    	
    	PropertyDescriptor[] pkPdArr = new PropertyDescriptor[pkPds.size()];
    	Column[] pkColumnsArr = new Column[pkColumns.size()];
    	pkPds.toArray(pkPdArr);
    	pkColumns.toArray(pkColumnsArr);
    	mapping.setPkColumns(pkColumnsArr);
    	mapping.setPkPropertyDescriptors(pkPdArr);

    	return mapping;
	}

	public PropertyDescriptor[] getPropertyDescriptors() {
		return propertyDescriptors;
	}

	public void setPropertyDescriptors(PropertyDescriptor[] propertyDescriptors) {
		this.propertyDescriptors = propertyDescriptors;
	}

	public Class getEntityType() {
		return entityType;
	}

	public void setEntityType(Class entityType) {
		this.entityType = entityType;
	}

	public PropertyDescriptor[] getPkPropertyDescriptors() {
		return pkPropertyDescriptors;
	}

	public void setPkPropertyDescriptors(PropertyDescriptor[] pkPropertyDescriptors) {
		this.pkPropertyDescriptors = pkPropertyDescriptors;
	}

	public void setColumns(Column[] columns) {
		this.columns = columns;
	}

	public void setTableName(String tableName) {
		this.tableName = tableName;
	}

	public Column[] getPkColumns() {
		return pkColumns;
	}

	public void setPkColumns(Column[] pkColumns) {
		this.pkColumns = pkColumns;
	}
	

}
